﻿#pragma once

#include "../df.h"

namespace df
{
	using namespace sdf;


	class Http;

	////////////////键////////////////////
#define HTTP_keyMethod "Method"
#define HTTP_keyHost "Host"
#define HTTP_keyAccept "Accept"
#define HTTP_keyAcceptEncoding "Accept-Encoding"
#define HTTP_keyConnection "Connection"
#define HTTP_keyCharset "Charset"
#define HTTP_keyContentType "Content-Type"
#define HTTP_keyContentLength "Content-Length"
#define HTTP_keyContentEncoding "Content-Encoding"
#define HTTP_keyX_Powered_By "X-Powered-By"
#define HTTP_keyKeepAlive "Keep-Alive"
#define HTTP_keyDate "Date"
#define HTTP_keyVary "Vary"
#define HTTP_keyUserAgent "User-Agent"
#define HTTP_keyTransferEncoding "Transfer-Encoding"
#define HTTP_keyCookie "Cookie"
#define HTTP_keyServer "Server"
#define HTTP_keyCacheControl "Cache-Control"
#define HTTP_keyPragma "Pragma"
#define HTTP_keyRange "Range"

	////////////////////////值///////////////////
#define HTTP_valKeepAlive "keep-alive"
#define HTTP_valChunked "chunked"
#define HTTP_valGzip "gzip"
#define HTTP_valAll "*/*"
#define HTTP_valNoCache "no-cache"
#define HTTP_valTextHtml "text/html"
#define HTTP_valUTF8 "charset=UTF-8"
#define HTTP_valTextPlain "text/plain"
#define HTTP_valJson "application/json"
#define HTTP_valGzipDeflate "gzip, deflate"

	class HttpHead
	{
	private:
		std::unordered_map<std::string, std::string> head_;
		static const int methodSize_ = 3;
		CCa method_[methodSize_];

		friend class Http;

	public:

		void Clear()
		{
			head_.clear();
		}

		void Set(CCa key, CCa val)
		{
			head_[key.ToString()].assign(val.c_str(), val.size());
		}

		void SetKeepAlive()
		{
			head_[HTTP_keyConnection] = HTTP_valKeepAlive;
		}

		void SetAcceptAll()
		{
			head_[HTTP_keyAccept] = HTTP_valAll;
		}

		template<class _NumT>
		void setContentLength(_NumT size) {
			auto & len = head_[HTTP_keyContentLength];
			len.clear();
			len << size;
		}


		template<class _NumT>
		void setRange(_NumT bytes)
		{
			auto & range = head_[HTTP_keyRange];
			range = "bytes=";
			range << bytes << "-";
		}

		void SetAcceptGzip()
		{
#ifdef DF_ENABLE_HTTP_GZIP
			head_[HTTP_keyAcceptEncoding] = HTTP_valGzip;
#endif
		}

		inline std::string & Get(CCa key)
		{
			return head_[key.ToString()];
		}

		

		int64_t getContentLength()
		{
			int64_t size = 0;
			df::StrToVar(head_[HTTP_keyContentLength], size);

			return size;
		}

		bool IsChunked()
		{
			auto para = head_.find(HTTP_keyTransferEncoding);
			if (para == head_.end())
				return false;

			if (para->second != HTTP_valChunked)
				return false;

			return true;
		}

		bool IsGzip()
		{
			auto para = head_.find(HTTP_keyContentEncoding);
			if (para == head_.end())
				return false;

			if (para->second != HTTP_valGzip)
				return false;

			return true;
		}

		inline std::unordered_map<std::string, std::string> & GetMap()
		{
			return head_;
		}

		int GetHttpCode()
		{
			int code = 0;
			df::StrToVar(method_[1], code);
			return code;
		}

		CCa GetHttpMsg()
		{
			return method_[2];
		}



		void ParseMethod()
		{

			for (int i = 0; i < methodSize_; i++)
			{
				method_[i].char_ = "";
				method_[i].length_ = 0;
			}

			auto method = head_.find(HTTP_keyMethod);
			if (method == head_.end())
				return;


			CCa str = method->second;
			int count = 0;
			method_[0].char_ = str.char_;
			method_[0].length_ = 0;

			for (intptr_t i = 0; i < str.length(); i++)
			{
				if (str[i] == ' ')
				{
					method_[count].length_ = str.char_ + i - method_[count].char_;
					count++;
					i++;

					method_[count].char_ = str.char_ + i;
					method_[count].length_ = str.char_ + str.length() - method_[count].char_;

					if (count >= 2)
						break;
				}

			}
		}



	};/////////class HttpHead




}/////////namespace df
